#!/bin/bash

function print_style {
    echo -e "\e[1;32m$1\e[0m"
}

passwd_content=$(cat /etc/passwd)

print_style "#############  1、检查 UID 的唯一性    ############# "
duplicate_uids=$(echo -e "$passwd_content" | awk -F: '{print $3}' | sort | uniq -d)

if [ -n "$duplicate_uids" ]; then
    print_style "错误：发现重复的 UID：$duplicate_uids \n"
else
    print_style  "UID 检查通过：所有 UID 唯一 \n"
fi

# 检查用户名的唯一性
duplicate_usernames=$(echo -e "$passwd_content" | awk -F: '{print $1}' | sort | uniq -d)

if [ -n "$duplicate_usernames" ]; then
    print_style "错误：发现重复的用户名：$duplicate_usernames \n"
else
    print_style  "用户名检查通过：所有用户名唯一 \n"
fi

# 2、用户鉴别信息复杂度定期更换
print_style "#############  2、用户鉴别信息复杂度定期更换    ############# "
# 读取并检查密码策略
cp /etc/login.defs /etc/login.defs.bak
PASS_MAX_DAYS=$(grep "^PASS_MAX_DAYS" /etc/login.defs | awk '{print $2}')
PASS_MIN_DAYS=$(grep "^PASS_MIN_DAYS" /etc/login.defs | awk '{print $2}')
PASS_MIN_LEN=$(grep "^PASS_MIN_LEN" /etc/login.defs | awk '{print $2}')
PASS_WARN_AGE=$(grep "^PASS_WARN_AGE" /etc/login.defs | awk '{print $2}')

# 修改密码策略（可根据需要修改）
NEW_PASS_MAX_DAYS=90
NEW_PASS_MIN_DAYS=0
NEW_PASS_MIN_LEN=8
NEW_PASS_WARN_AGE=7

# 修改密码登录有效期时间
if [ "$PASS_MAX_DAYS" -ne "$NEW_PASS_MAX_DAYS" ]; then
    sed -i "s/PASS_MAX_DAYS.*/PASS_MAX_DAYS $NEW_PASS_MAX_DAYS/" /etc/login.defs
    print_style "修改后的密码登录有效期时间: $NEW_PASS_MAX_DAYS 天"
fi

# 修改密码最短修改时间
if [ "$PASS_MIN_DAYS" -ne "$NEW_PASS_MIN_DAYS" ]; then
    sed -i "s/PASS_MIN_DAYS.*/PASS_MIN_DAYS $NEW_PASS_MIN_DAYS/" /etc/login.defs
    print_style "修改后的密码最短修改时间: $NEW_PASS_MIN_DAYS 天"
fi

# 修改密码最小长度
if [ "$PASS_MIN_LEN" -ne "$NEW_PASS_MIN_LEN" ]; then
    sed -i "s/PASS_MIN_LEN.*/PASS_MIN_LEN $NEW_PASS_MIN_LEN/" /etc/login.defs
    print_style "修改后的密码最小长度: $NEW_PASS_MIN_LEN 个字符"
fi

# 修改密码过期前提前提醒天数
if [ "$PASS_WARN_AGE" -ne "$NEW_PASS_WARN_AGE" ]; then
    sed -i "s/PASS_WARN_AGE.*/PASS_WARN_AGE $NEW_PASS_WARN_AGE/" /etc/login.defs
    print_style "修改后的密码过期前提前提醒天数: $NEW_PASS_WARN_AGE 天"
fi

# 3、服务器密码复杂的策略
print_style "#############  3、服务器密码复杂的策略    ############# "
# 修改路基
system_auth_file=/etc/pam.d/system-auth
system_login_local=/etc/pam.d/login
system_login_sshd=/etc/pam.d/sshd
cp $system_auth_file $system_auth_file.bak
cp $system_login_local $system_login_local.bak
cp $system_login_sshd $system_login_sshd.bak
# 策略模块
system_auth_local_password=pam_cracklib.so
system_auth_login=pam_tally2.so

function modify_file_password {
    local file_path="$1"
    local module_to_add="pam_cracklib.so"
    local module_line="password    requisite     $module_to_add   retry=5 difok=3 minlen=10 ucreddir=-1 lcredit=-3 dcredit=-3"
    if grep -q "$module_to_add" "$file_path"; then
	sed -i '/pam_pwquality.so $module_to_add/c\$module_line' "$file_path"
        print_style "$module_to_add 模块已注释，新模块添加完成"
    else
        sed -i "/pam_pwquality.so/a $module_line" "$file_path"
        print_style "$module_to_add 模块不存在，新模块添加完成"
    fi
}

for i in "$system_auth_file"; do
    sleep 1
    modify_file_password "$i"
    result=$(grep "$system_auth_local_password" "$i")
    if [[ -n "$result" ]]; then
        print_style "$system_auth_local_password 模块添加完成"
    else
        print_style "$system_auth_local_password 模块添加失败"
        exit
    fi
done

# 4、登录失败处理 system,local,sshd
print_style "########### 4、登录失败处理 system,local,sshd  ########### "
function modify_file_auth {
    local file_path="$1"
    if grep -q "pam_tally2.so " "$file_path"; then
        sed -i '/pam_tally2.so/c\auth    required     pam_tally2.so   onerr=fail deny=5 unlock_time=300 even_deny_root root_unlock_time=10' "$file_path"
        print_style "pam_tally2.so 模块已注释，新模块添加完成"
    else
        sed -i '3a auth    required     pam_tally2.so  onerr=fail deny=5 unlock_time=300 even_deny_root root_unlock_time=10'  "$file_path"
        print_style "pam_tally2.so 模块不存在，新模块添加完成"
    fi
}

for i in "$system_auth_file" "$system_login_local" "$system_login_sshd"; do
    modify_file_auth $i
    sleep 1
    result=$(grep "$system_auth_login" "$i")
    if [[ -n "$result" ]]; then
        print_style "$i 模块添加完成"
    else
        print_style "$i 模块添加失败"
        exit
    fi
done

# 5 服务检查 telnet服务和端口
print_style "########### 5 服务检查 telnet服务和端口 ############ "
sleep 1
systemctl list-unit-files | grep telnet
if [ $? -eq 0 ]; then
    systemctl disable --now telnet
else
    print_style "telnet 已永久关闭"
fi

telnet_pid=$(netstat -ntlp | awk '$4 ~ /:23$/ {split($7, a, "/"); print a[1]}')
print_style "Telnet 进程 ID: $telnet_pid"
if [ $? -eq 0 ]; then
    print_style 'Telnet 进程不存在或无法获取进程 ID'
else
    kill -9 "$telnet_pid"
fi

# 6 默认权限修改
print_style "#############  6 默认权限修改    ############# "
sleep 1
um=$(umask)
if [ $um -eq 0027 ]; then
    print_style 'umask 默认参数合格'
else
    sed -i 's/umask 022/umask 027/' /etc/profile
    print_style '已修改默认值'
fi


